package com.frejoys.notify.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alipay.easysdk.factory.Factory;
import com.frejoys.common.aop.Authority;
import com.frejoys.common.aop.Authorization;
import com.frejoys.common.constant.CommonConstant;
import com.frejoys.common.enums.EOrderType;
import com.frejoys.common.enums.EPayStatus;
import com.frejoys.common.enums.EVerify;
import com.frejoys.common.util.CacheKeyUtil;
import com.frejoys.common.vo.order.AttachVo;
import com.frejoys.service.EventPublisherService;
import com.frejoys.service.OrderService;
import com.frejoys.service.PayService;
import com.frejoys.service.VoiceMessageService;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyV3Result;
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyV3Result;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * @author wangzhicheng
 * @version 1.0
 * @date 2024/4/17 16:44
 */
@Tag(name = "支付回调", description = "支付回调")
@RestController
@RequiredArgsConstructor
@RequestMapping(CommonConstant.routePrefixNotify)
@Authorization(Authority.Public)
@Slf4j
public class NotifyController {

    private final RedissonClient redissonClient;

    private final WxPayService wxPayService;

    private final OrderService orderService;

    private final PayService payService;

    private final EventPublisherService eventPublisherService;

    private final VoiceMessageService voiceMessageService;


    @Operation(summary = "微信支付回调")
    @PostMapping("/wxpay")
    public JSONObject wxpay(@RequestBody String jsonData, HttpServletRequest request, HttpServletResponse response) {
        JSONObject jsonObject = new JSONObject();

        try {

            WxPayNotifyV3Result v3Result = wxPayService.parseOrderNotifyV3Result(jsonData, payService.wxSignatureHeader(request));

            if (null != v3Result && v3Result.getResult().getTradeState().equals(CommonConstant.SUCCESS)) {

                RLock lock = redissonClient.getLock(CacheKeyUtil.orderPayNotifyLockCacheKey(v3Result.getResult().getOutTradeNo()));

                if (lock.tryLock()) {
                    try {
                        Long orderSn = Long.valueOf(v3Result.getResult().getOutTradeNo());

                        // 核销状态
                        Integer verify = null;

                        // 获取附属信息
                        String attach = v3Result.getResult().getAttach();
                        if (StrUtil.isNotEmpty(attach)) {
                            AttachVo attachVo = JSONUtil.toBean(attach, AttachVo.class);
                            if (attachVo != null) {
                                // 虚拟订单
                                if (attachVo.getType() > EOrderType.goodsOrder.getValue()) {
                                    verify = EVerify.inProgress.getValue();
                                }
                            }
                        }

                        // 处理订单
                        boolean b = orderService.notifyDisposeOrder(orderSn, verify);
                        if (b) {

                            // 实物订单需要核销码，虚拟订单不需要核销码
                            if (verify == null) {
                                eventPublisherService.dispatchOrderQrCodeService(orderSn);
                            } else {
                                // 语音播报
                                voiceMessageService.voicePlay(orderSn);
                            }

                            response.setStatus(HttpServletResponse.SC_OK);
                            return jsonObject;
                        }
                    } finally {
                        if (lock.isLocked() && lock.isHeldByCurrentThread()) {
                            lock.unlock();
                        }
                    }
                }

            }


        } catch (WxPayException e) {
            e.printStackTrace();
        }

        response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        return jsonObject;
    }

    @Operation(summary = "微信退款回调")
    @PostMapping("/wxpay/refund")
    public JSONObject wxpayRefund(@RequestBody String jsonData, HttpServletRequest request, HttpServletResponse response) {
        JSONObject jsonObject = new JSONObject();

        try {
            WxPayRefundNotifyV3Result v3Result = wxPayService.parseRefundNotifyV3Result(jsonData, payService.wxSignatureHeader(request));

            if (null != v3Result && v3Result.getResult().getRefundStatus().equals(CommonConstant.SUCCESS)) {

                RLock lock = redissonClient.getLock(CacheKeyUtil.orderRefundNotifyLockCacheKey(v3Result.getResult().getOutTradeNo()));

                if (lock.tryLock()) {
                    try {
                        // 更新为已退款
                        boolean b = orderService.refundCallbackOrderPayStatus(Long.valueOf(v3Result.getResult().getOutTradeNo()), EPayStatus.refunding.getValue(), EPayStatus.refund.getValue());
                        if (b) {
                            response.setStatus(HttpServletResponse.SC_OK);
                            return jsonObject;
                        }
                    } finally {
                        if (lock.isLocked() && lock.isHeldByCurrentThread()) {
                            lock.unlock();
                        }
                    }
                }


            }
        } catch (WxPayException e) {
            e.printStackTrace();
        }

        response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        return jsonObject;
    }

    @Operation(summary = "支付宝支付回调")
    @PostMapping("/alipay")
    public String alipay(HttpServletRequest request) {
        Map<String, String> params = new HashMap<>();
        Map<String, String[]> requestParams = request.getParameterMap();

        for (String name : requestParams.keySet()) {
            params.put(name, request.getParameter(name));
        }

        try {
            boolean result = Factory.Payment.Common().verifyNotify(params);

            if (result && params.get("trade_status").equals("TRADE_SUCCESS")) {

                RLock lock = redissonClient.getLock(CacheKeyUtil.orderPayNotifyLockCacheKey(params.get("out_trade_no")));

                if (lock.tryLock()) {
                    try {

                        Long orderSn = Long.valueOf(params.get("out_trade_no"));

                        // 核销状态
                        Integer verify = null;

                        // 获取附属信息
                        String attach = params.get("body");
                        if (StrUtil.isNotEmpty(attach)) {
                            AttachVo attachVo = JSONUtil.toBean(attach, AttachVo.class);
                            if (attachVo != null) {
                                // 虚拟订单
                                if (attachVo.getType() > EOrderType.goodsOrder.getValue()) {
                                    verify = EVerify.inProgress.getValue();
                                }
                            }
                        }

                        // 处理订单
                        boolean b = orderService.notifyDisposeOrder(orderSn, verify);

                        if (b) {
                            // // 获取附属信息
                            // String attach = params.get("body");
                            // if (StrUtil.isNotEmpty(attach)) {
                            //
                            //     AttachVo attachVo = JSONUtil.toBean(attach, AttachVo.class);
                            //     if (attachVo != null) {
                            //         // 是否调用到账语音接口
                            //         System.out.println("到账语音信息：");
                            //         System.out.println(attachVo);
                            //     }
                            //
                            // }

                            // 实物订单需要核销码，虚拟订单不需要核销码
                            if (verify == null) {
                                eventPublisherService.dispatchOrderQrCodeService(orderSn);
                            } else {
                                // 语音播报
                                voiceMessageService.voicePlay(orderSn);
                            }

                            return "success";
                        }
                    } finally {
                        if (lock.isLocked() && lock.isHeldByCurrentThread()) {
                            lock.unlock();
                        }
                    }
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return "fail";
    }


}
